/*
 * Copyright (C) 2008 The Android Open Source Project
 * Copyright (c) <2013-2018>, <Huawei Technologies Co., Ltd>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*----------------------------------------------------------------------------
 * Notice of Export Control Law
 * ===============================================
 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
 * applicable export control laws and regulations.
 *---------------------------------------------------------------------------*/

/**@defgroup semaphore Semaphore
 * @ingroup libc
 */


#ifndef _SEMAPHORE_H
#define _SEMAPHORE_H

#ifndef __LITEOS__
#include <sys/cdefs.h>
#else
#include "time.h"
#include "los_sem_pri.h"
#endif

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */


#ifndef __LITEOS__
struct timespec;

typedef struct {
  unsigned int count;
#ifdef __LP64__
  int __reserved[3];
#endif
} sem_t;
#else
#ifdef SEM_VALUE_MAX
#undef SEM_VALUE_MAX
/**
 * @ingroup semaphore
 * Maximum semaphore value.
 */
#define  SEM_VALUE_MAX      OS_SEM_COUNT_MAX
#endif

#ifdef SEM_NSEMS_MAX
#undef SEM_NSEMS_MAX
#endif

/**
 * @ingroup semaphore
 * Maximum number of supported semaphores.
 */
#define  SEM_NSEMS_MAX      LOSCFG_BASE_IPC_SEM_LIMIT

/**
 * @ingroup semaphore
 * API parameter sructure
 */

typedef struct posix_sem
{
    LosSemCB* sem;        /**< Semaphore attribute structure*/
} sem_t;
#endif

#define SEM_FAILED NULL

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to destroy a semaphore that has a specified descriptor.
 *@attention
 *<ul>
 *<li> If the semaphore has no waiters, it will be reclaimed.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully destroyed.
 *@retval -1    The semaphore fails to be destroyed, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>EBUSY</b>: The semaphore has waiters.</li>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_init
 *@since Huawei LiteOS V100R001C00
 */
int sem_destroy(sem_t *sem);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to get the value of  a semaphore with a specified semaphore descriptor.
 *@attention
 *<ul>
 *<li> The parameter "pshared" is not supported, the semaphore is shared between threads by default.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully obtained.
 *@retval -1    The semaphore fails to obtained, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_post | sem_timedwait | sem_trywait
 *@since Huawei LiteOS V100R001C00
 */
int sem_getvalue(sem_t *sem, int *sval);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to initialize a semaphore with a specified value.
 *@attention
 *<ul>
 *<li> The parameter "pshared" is not supported, the semaphore is shared between threads by default.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully destroyed.
 *@retval -1    The semaphore fails to be destroyed, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>ENOMEM</b>: The specified value exceeds SEM_VALUE_MAX.</li>
 * <li><b>ENOSPC</b>: The limit on semaphores(SEM_NSEMS_MAX) has been reached,
 *                    there is no enough semaphores to be used.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_destroy
 *@since Huawei LiteOS V100R001C00
 */
int sem_init(sem_t *sem, int pshared, unsigned int value);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to unlock a semaphore with a specified semaphore descriptor.
 *@attention
 *<ul>
 *<li> If no threads were blocked waiting for the semaphore to become unlocked,
 *    the semaphore value is simply incremented; otherwise one of the threads blocked
 *    waiting for the semaphore shall be allowed to be waken up.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully unlocked.
 *@retval -1    The semaphore fails to be unlocked, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>ENOMEM</b>: The semaphore value exceeds SEM_VALUE_MAX.</li>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_timedwait | sem_trywait | sem_wait
 *@since Huawei LiteOS V100R001C00
 */
int sem_post(sem_t *sem);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to wait a semaphore with a specified semaphore descriptor by a given time.
 *@attention
 *<ul>
 *<li> The expiry time must be later than the current time.</li>
 *<li> The wait time is a relative time.</li>
 *<li> If the wait time is small than one system tick(10ms by defalut),
 *    the thread would be forced to be blocked by one system tick.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully locked.
 *@retval -1    The semaphore fails to be locked, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * <li><b>EPERM</b>: Waiting a semaphore during the task scheduler was locked is not supported.</li>
 * <li><b>EINTR</b>: Waiting a semaphore in and ISR is not supported.</li>
 * <li><b>ETIMEDOUT</b>: The semaphore could not be locked before the specified timeout expired.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_timedwait | sem_trywait | sem_wait
 *@since Huawei LiteOS V100R001C00
 */
int sem_timedwait(sem_t *sem, const struct timespec *timeout);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to wait a semaphore only if no threads waiting for it.
 *@attention
 *<ul>
 *<li> If there is no threads waiting for it, it is similar with sem_wait; otherwise it return -1 directly.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully locked.
 *@retval -1    The semaphore fails to be locked, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * <li><b>EAGAIN</b>: There is at least one thread wait for it.</li>
 * <li><b>EPERM</b>: Waiting a semaphore during the task scheduler was locked is not supported.</li>
 * <li><b>EINTR</b>: Waiting a semaphore in and ISR is not supported.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_timedwait | sem_wait
 *@since Huawei LiteOS V100R001C00
 */
int sem_trywait(sem_t *sem);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to wait a semaphore for ever.
 *@attention
 *<ul>
 *<li> If there is no threads waiting for it, it is similar with sem_wait; otherwise it return -1 directly.</li>
 *</ul>
 *
 *@retval  0    The semaphore is successfully locked.
 *@retval -1    The semaphore fails to be locked, with either of the following error codes in errno.
 *
 *@par Errors
 * <ul>
 * <li><b>EINVAL</b>: Invalid parameter.</li>
 * <li><b>EPERM</b>: Waiting a semaphore during the task scheduler was locked is not supported.</li>
 * <li><b>EINTR</b>: Waiting a semaphore in and ISR is not supported.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_timedwait | sem_trywait
 *@since Huawei LiteOS V100R001C00
 */
int sem_wait(sem_t *sem);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to Initialize and open a semaphore that has a specified descriptor.
 *@attention
 *<ul>
 *<li> This interface is not supported, It will always return NULL.</li>
 *</ul>
 *
 *@retval NULL    This interface is not supported, It will always return NULL.
 *
 *@par Errors
 * <ul>
 * <li><b>ENOSYS</b>: This interface is not supported.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_close
 *@since Huawei LiteOS V100R001C00
 */
sem_t* sem_open(const char*, int, ...);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to close a semaphore that has a specified descriptor.
 *@attention
 *<ul>
 *<li> This interface is not supported, It will always return -1.</li>
 *</ul>
 *
 *@retval -1    This interface is not supported, It will always return -1.
 *
 *@par Errors
 * <ul>
 * <li><b>EINVAL</b>: Invalid semaphore descriptor.</li>
 * <li><b>ENOSYS</b>: This interface is not supported.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_open
 *@since Huawei LiteOS V100R001C00
 */
int sem_close(sem_t*);

/**
 *@ingroup semaphore
 *
 *@par Description:
 *This API is used to remove a semaphore that has a specified descriptor.
 *@attention
 *<ul>
 *<li> This interface is not supported, It will always return -1.</li>
 *</ul>
 *
 *@retval -1    This interface is not supported, It will always return -1.
 *
 *@par Errors
 * <ul>
 * <li><b>ENOSYS</b>: This interface is not supported.</li>
 * </ul>
 *
 *@par Dependency:
 *<ul><li>semaphore.h</li></ul>
 *@see sem_open | sem_close
 *@since Huawei LiteOS V100R001C00
 */
int sem_unlink(const char*);


#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */

#endif /* _SEMAPHORE_H */
